#include <iostream>
#include <cstring>
#include "shell.h"
#include "tool.h"


/*
TODO 
1.@S=1  上报之后清空。
2.错误命令，提示并不执行。、

3.格式错误，提示。
@IF  分支跳转
*/

//void ef_set_env(char* key,char* val){
//    printf("%s:%s\n",key,val);      //模拟easyflash
//}

//char* ef_get_env(char* key){
//    return "ef_get_env";
//}

shell_variable shell_var;
int UART_Init(uint32_t buad_rate){
    printf("----> set baud rate: %d\n",buad_rate);
    return 0;
}

void shell_init(){              //默认状态可以保存到ef中
    printf("current shell version: %s\n",SHELL_VERSION);
    shell_var={0};

    clean_node_list();
    clean_shell_buf();
    shell_var.baud_rate=DEFAULT_BAUD_RATE; //默认波特率: 115200
    shell_var.upload_per=1;     //默认上报周期: 1次1报
    shell_var.recv_resp=1;      //默认接收应答
//    shell_var.cut_sta=0;
//    shell_var.cut_size=0;
//    shell_var.echo_cmd=0;
//    shell_var.shell_loop=0;
//    shell_var.wait_loop=0;
//    shell_var.send_data=NULL;
//    shell_var.inform_format=0;  //默认采集数据格式: 原始
//    shell_var.collect_len=0;
//    shell_var.packet_num=0;
//    shell_var.shell_len=0;

}
/***** 清空链表 *****/
void clean_node_list(){
    cmd_node* p=shell_var.head;
    if(0==shell_var.node_num)
        return;
    for(int i=0;i<shell_var.node_num;i++){
        free(p->key);
        p->key=NULL;

        free(p->val);
        p->val = NULL;

        p = p->next;
    }
    shell_var.node_num=0;
    shell_var.head=NULL;
    shell_var.tail=NULL;
    memset(shell_var.node_group,0,sizeof(shell_var.node_group));
}

void clean_shell_buf(){
    memset(shell_var.shell_buf,0,sizeof(shell_var.shell_buf));
    shell_var.shell_len=0;
}
uint16_t get_node_num(){
    return shell_var.node_num;
}
void set_node_num(uint16_t new_num){
    shell_var.node_num=new_num;
}
cmd_node* get_node_bypos(int pos){
    cmd_node* p=shell_var.head;
    if(pos>get_node_num()) {
        printf("----> position overstep unable to get node\n");
        return NULL;
    }
    for(int i=0;i<pos;i++){
        p=p->next;
    }
    return p;
}

/***** 删除指定位置的节点 （链表顺序）*****/
int drop_node_bypos(int pos){
    cmd_node* p=NULL;
    if(NULL==(p=get_node_bypos(pos))){
        printf("not find node , drop node failed\n");
        return -1;
    }
    p->next->previous=p->previous;      //重建邻居关系
    p->previous->next=p->next;

    free(p->key);
    free(p->val);
    p->previous=NULL;
    p->next=NULL;
    --shell_var.node_num;
    return 0;
}

int drop_node_bynode(cmd_node* node){
    if(NULL==get_node_bykey(node->key)){    //检查是否存在该节点
        printf("not find node , drop node failed\n");
        return -1;
    }
    node->next->previous=node->previous;      //重建邻居关系
    node->previous->next=node->next;
    free(node->key);
    free(node->val);
    node->previous=NULL;
    node->next=NULL;
    --shell_var.node_num;
    return 0;
}
cmd_node* get_node_bykey(char* key){
    cmd_node* p;
    p=shell_var.head;
    for(int i=0;i<shell_var.node_num;i++){
        if(!strncmp(key,p->key,strlen(key))){
            return p;
        }
        p=p->next;
    }
    return NULL;
}
/***** 指定位置 插入节点（指定位置的节点后移 新节点占用指定位置） *****/
int insert_pos(int pos, cmd_node* node) {
    cmd_node *p;
    //int group_len=sizeof(shell_var.node_group) / sizeof(cmd_node);
    if(0==shell_var.node_num){
        shell_var.tail=node;          //初始时，头节点=表节点
        shell_var.head=node;
        shell_var.head->next=shell_var.tail;
        shell_var.head->previous=shell_var.tail;
        shell_var.tail->next=shell_var.head;
        shell_var.tail->previous=shell_var.head;
    }else {
        p = shell_var.head;
        for (int i = 0; i < pos; i++) {
            p = p->next;
        }
        p->previous->next = node;
        node->previous = p->previous;
        node->next = p;
        p->previous = node;
    }
    ++shell_var.node_num;
    shell_var.node_num %= NODE_GROUP_NUM;
    return 0;
}

/***** 尾插节点 *****/
int insert_tail(cmd_node* node){
    //int group_len=sizeof(shell_var.node_group) / sizeof(cmd_node);
    if(shell_var.node_num==0){
        shell_var.tail=node;          //初始时，头节点=表节点
        shell_var.head=node;
        shell_var.head->next=shell_var.tail;
        shell_var.head->previous=shell_var.tail;
        shell_var.tail->next=shell_var.head;
        shell_var.tail->previous=shell_var.head;
    }else{
        shell_var.tail->next=node;
        node->previous=shell_var.tail;
        node->next=shell_var.head;
        shell_var.head->previous=node;
        shell_var.tail=node;          //node成为尾节点
    }
    ++shell_var.node_num;
    shell_var.node_num %= NODE_GROUP_NUM;
    return 0;
}

/***** 返回节点索引（链表顺序） *****/
int get_node_pos(cmd_node* node,int num){
    int i=0;
    cmd_node* p;
    p=shell_var.head;
    for(i=0;i<shell_var.node_num;i++){
        if((!strncmp(node->key,p->key,strlen(node->key)))&&(!strncmp(node->val,p->val,strlen(node->val)))){
            //更严格是判断next和previous是否一致
        if(num>1) {
            printf("----> ignore a node\n");
            --num;
        }else
            return i;
        }
        p=p->next;
    }
    printf("----> not find node: %s\n",node->key);
    return -1;
}
/* @E=1@T=1@DO1=1@D=10S@M=1@B=420@D=20S@D=50S@C=9600@L=1,6@V=1@b=2@a=1
 *
 * 脚本执行到 L 指令时立即跳转到指定的 M 标记点，直到达到循环指定的次数后，继续往后面执行
 * */
/***** 拆包，插入链表 *****/
int unpack(char* buf,int buf_len){
    char val_buf[MAX_VAL_LEN];
    int val_len=0;
    int i=0;
//    clean_node_list();        //释放内存
    if(0>=(shell_var.shell_len=buf_len)||strncmp(MARK_1,buf,strlen(MARK_1))){
        printf("----> unpack failed\n");
        return -1;
    }

    //static int group_len=sizeof(shell_var.node_group) / sizeof(cmd_node);
    for(;;) {
        ++i;
        memset(val_buf,0,sizeof(val_buf));

        shell_var.node_group[shell_var.node_num].key=(char*)malloc(sizeof(char)*MAX_KEY_LEN);       // TODO 输入非脚本内容也会申请内存 最终将内存溢出
        memset(shell_var.node_group[shell_var.node_num].key,0,sizeof(char)*MAX_KEY_LEN);
        if(0>str_split(shell_var.node_group[shell_var.node_num].key,buf,MARK_1,i,MARK_2,i)){
            //printf("----> node_num: %d\n",shell_var.node_num);        //打印节点数
            return shell_var.node_num;
        }
        if(0>(val_len=str_split(val_buf,buf,MARK_2,i,MARK_1,i+1))) {        //拿到末尾的val
            val_len=shell_var.shell_len-(str_search(buf,MARK_2,i)+1) ;
            strncpy(val_buf,&buf[str_search(buf,MARK_2,i)+1],(size_t)val_len);
            //printf("shell_var.shell_var.tail val len: %d\n",shell_var.shell_len-(str_search(buf,"=",i)+1));
        }
        shell_var.node_group[shell_var.node_num].val=(char*)malloc((sizeof(char)*val_len)+1);
        //memset(shell_var.node_group[shell_var.node_num].val,0,(sizeof(char)*val_len)+1);       //全部填充结束符
        strncpy(shell_var.node_group[shell_var.node_num].val,val_buf,(size_t)val_len);
        shell_var.node_group[shell_var.node_num].val[(sizeof(char)*val_len)]='\0';       //补上结束符

        //ef_set_env(shell_var.node_group[shell_var.node_num].key,val_buf);      //the same key saved to ef will be overwrite

        insert_tail(&shell_var.node_group[shell_var.node_num]);
        //search_cmd_handle(&shell_var.node_group[shell_var.node_num-1]);     //插入后立即执行
    }
    return shell_var.node_num;
}

//@E=1@T=2@P=?@W=2@d=4@D=4S@F=1@B=4800@C=9600@V=1@W=2@d=4@S=1

#define T 1000      //1秒
void delay(cmd_node* node){
    char unit;
    uint32_t val;
    sscanf(node->val,"%d%c",&val,&unit);
    switch(unit){
        case 'S':
            val*=T;
            break;
        case 'M':
            val*=60*T;
            break;
        case 'H':
            val*=3600*T;
            break;
        case 'm':
            //val=val
            break;
        default:
            return;
    }
    //_sleep(val);
    printf("----> delay: %d ms\n",val);
}

/***** mark *****/
void mark(cmd_node* node){
    shell_var.wait_loop=1;        //开始等待L ， M -> L间的命令在未等到L时，全部忽略
    printf("----> M=%s wait L\n",node->val);
}

void loop(cmd_node* node) {

    if (shell_var.wait_loop != 1) {
        printf("no mark -> M loop failed\n");		//需要测试
        return;
    }
    shell_var.wait_loop=0;
    int L_index=0,mark_num=0,loop_num=0;
    int mark_tmp=0;
    cmd_node* p;
    sscanf(node->val,"%d,%d",&mark_num,&loop_num);
    printf("----> mark: %d loop: %d\n", mark_num,loop_num);
    if(0>(L_index=get_node_pos(node,1))){
        printf("----> not find L position\n");
        return;
    }
    //printf("L_index: %d\n", L_index);
    p=node;
    for (int i=0;i<L_index;i++) {
        p=p->previous;
        //printf("find M: %s\n",tmp.val);
        if(!strncmp("M",p->key,strlen("M"))){      //往前 找到最近的 M
            sscanf(p->val,"%d",&mark_tmp);
            if(mark_tmp==mark_num){      //例：M=1     L=1,4
                printf("----> M to L interval: %d\n",i);
                printf("----> M index: %d\n----> L index: %d\n",(L_index-i)-1,L_index);
                while(loop_num--) {
                    execute(&shell_var.node_group[L_index-i],i);
                }
            }
        }
    }
}

/***** 发送区插入校验 *****/
void insert_check(cmd_node* node){
    uint16_t val=0,check;
    uint8_t buf[2];
    sscanf(node->val,"%d",&val);
    switch(val){
        case 1:
            check=get_crc((uint8_t*)shell_var.shell_buf,shell_var.shell_len);       //计算接收到的所有数据的校验
            break;
        case 2:
            check=get_sum((uint8_t*)shell_var.shell_buf,shell_var.shell_len);
            break;
        default:
            return;
    }
    buf[0]=(uint8_t)(check>>8);
    buf[1]=(uint8_t)(check);
    write_collect(&buf[0],sizeof(buf),0);
    printf("----> check: %x\n",check);
/*
    在链表内插入
    #define MAX_CHECK_LEN   6
    int val=0,len=0,check;
    char buf[MAX_CHECK_LEN];
    sscanf(node->val,"%d",&val);
    if(1==val) {            //插入crc校验
        shell_var.node_group[shell_var.node_num].key = (char*)malloc(strlen("CRC")+1);
        strcpy(shell_var.node_group[shell_var.node_num].key,"CRC");
        shell_var.node_group[shell_var.node_num].key[strlen("CRC")]='\0';
        check=get_crc((uint8_t*)shell_var.shell_buf,strlen(shell_var.shell_buf));
        printf("----> insert crc check: %x\n",check);
    }else if(2==val){       //插入和校验
        shell_var.node_group[shell_var.node_num].key = (char*)malloc(strlen("SUM")+1);
        strcpy(shell_var.node_group[shell_var.node_num].key,"SUM");
        shell_var.node_group[shell_var.node_num].key[strlen("SUM")]='\0';
        check=get_sum((uint8_t*)shell_var.shell_buf,strlen((char*)shell_var.shell_buf));
        printf("----> insert sum check: %x\n",check);
    }
    len=sprintf(buf,"%x",check);
    shell_var.node_group[shell_var.node_num].val=(char*)malloc(len+1);
    strncpy(shell_var.node_group[shell_var.node_num].val,buf,len);
    shell_var.node_group[shell_var.node_num].val[len]='\0';

    insert_at(get_node_index(node,1),&shell_var.node_group[shell_var.node_num]);
*/
}

/***** 设置回传 *****/
void set_echo(cmd_node* node) {
    sscanf(node->val, "%d", &shell_var.echo_cmd);
    if (0 == shell_var.echo_cmd) {
        printf("----> no echo cmd\n");
    } else if (1 == shell_var.echo_cmd) {
        //printf("----> echo cmd\n");
    }
}

/***** 设置脚本无限循环 *****/
void set_loop_shell(cmd_node* node){
    sscanf(node->val,"%d",&shell_var.shell_loop);
    if(0==shell_var.shell_loop){
        //printf("----> no loop execution shell cmd\n");
    }else if(1==shell_var.shell_loop){
        printf("----> loop execution shell cmd\n");
    }
}

/***** 设置上报周期 *****/
void set_inform_period(cmd_node* node){
    sscanf(node->val,"%d",&shell_var.upload_per);
    printf("----> set upload period: %d\n",shell_var.upload_per);

}

/***** 上报数据（上报后清空发送区） *****/
//@E=1@T=1@P=?@W=2@CUT=2,3      CUT指令，从0开始
void inform(){
    if(0==shell_var.collect_len)
        return;
    if(shell_var.cut_size!=0){
        shell_var.send_data(&shell_var.collect_buf[shell_var.cut_sta], shell_var.cut_size);
    }else {
        shell_var.send_data(&shell_var.collect_buf[0], shell_var.collect_len);
    }
    clean_collect();        //发送完后清空采集的数据
}

/***** 回传控制函数 *****/
//  @E=1@T=2@W=3@d=4@D=4@B=4800@C=9600@W=2@d=4
void transmit_control(){
    static int cont=0;
    if(1==shell_var.echo_cmd){
        ++cont;
        cont%=shell_var.upload_per;
        if(cont==0){
            inform();
            //printf(">>>>> upload data\n");
        }
    }else{
        clean_collect();        //发送完后清空采集的数据
    }
}

/***** 立即上报 （就算 @E=0 也会上报）*****/
void at_once_inform(cmd_node* node) {
    printf("----> at once inform\n");
    inform();       //立即上报
    //sscanf(node->val, "%s", node->val);
}

/***** 设置上报数据格式 *****/
void set_inform_format(cmd_node* node){
    sscanf(node->val,"%d",&shell_var.inform_format);
    if(0==shell_var.inform_format){
        printf("----> set inform format: original\n");
    }else if(1==shell_var.inform_format){
        printf("----> set inform format: 0x01 => \"01\"\n");       //数据 01 03 02（3个HEX数据）, 转换后 "0103020001AC8F"
    }
}

/***** 写入采集数据到发送区（默认直接写入 可以通过format=1或@F=1写hex=>str） *****/
void write_collect(uint8_t* data,int length,int format){
    if(0==shell_var.recv_resp){
        return;     //TODO   直接忽略设备应答消息？
    }
    if((shell_var.inform_format==1)||(format==1)){
        if ((2*length + shell_var.collect_len) > MAX_COLLECT_LEN) {
            length = (MAX_COLLECT_LEN - shell_var.collect_len)/2;       //TODO
            printf(">>>>> cut write collect data length\n");
        }
        int offset=0;
        char buf[2];
        for(int i=0;i<length;i++){
            offset=sprintf(&buf[0],"%02x",data[i]);
            memcpy(&shell_var.collect_buf[shell_var.collect_len], &buf[0],offset);
            shell_var.collect_len += offset;
        }
    }else if(shell_var.inform_format==0){
        if ((length + shell_var.collect_len) > MAX_COLLECT_LEN) {
            length = MAX_COLLECT_LEN - shell_var.collect_len;
            printf(">>>>> cut write collect data length\n");
        }
        memcpy(&shell_var.collect_buf[shell_var.collect_len], &data[0], (size_t) length);
        shell_var.collect_len += length;
    }
}

/***** 写入包序号到发送区 *****/
void set_packet_num(cmd_node* node){        //4字节的包序号
    uint8_t buf[4];
    if(0!=strncmp(node->val,"?",strlen("?"))){
        return;
    }
    buf[0]=(uint8_t)(shell_var.packet_num>>24);
    buf[1]=(uint8_t)(shell_var.packet_num>>16);
    buf[2]=(uint8_t)(shell_var.packet_num>>8);
    buf[3]=(uint8_t)(shell_var.packet_num>>0);
    write_collect(&buf[0],4,0);
}

/***** 清空发送区 *****/
void clean_collect(){
    memset(shell_var.collect_buf,0,sizeof(shell_var.collect_buf));
    shell_var.collect_len=0;
}

/***** 设置波特率 *****/
void set_baud_rate(cmd_node* node){
    //uint32_t baud_rate=0;
    if(0>=str_search(node->key,",",1)){
        sscanf(node->val,"%d",&shell_var.baud_rate);
    }else {
        sscanf(node->val,"%d,",&shell_var.baud_rate);
        printf("----> exist config\n");
        //  TODO    实现配置
    }
    if(0!=shell_var.baud_rate) {
        UART_Init(shell_var.baud_rate);
    }
}

/***** 截取数据发送 脚本执行完后 恢复为不截取*****/
//@E=1@T=1@P=?@W=2@CUT=2,333      CUT指令，从0开始
void cut_collect(cmd_node* node){
    int sta,size;
    if(!strcmp(node->val,"")){      //@CUT=
        printf("----> cancel the cut\n");
        shell_var.cut_sta=0;
        shell_var.cut_size=0;
        return;
    }
    sscanf(node->val,"%d,%d",&sta,&size);
    if(sta>=MAX_COLLECT_LEN||size>MAX_COLLECT_LEN){
        printf("----> cut address error\n");
        return;
    }
    if(sta>shell_var.collect_len){                        //起始地址 在实际保存的数据末尾 后部
        printf("----> cut start address error\n");
        return;
    }
    if(sta+size>shell_var.collect_len){     //截取数据长度 超出实际保存的数据末尾
        printf("----> adjust cut size\n");
        size=shell_var.collect_len-sta;
    }
    shell_var.cut_sta=sta;
    shell_var.cut_size=size;
    printf("----> cut start: %d size: %d\n",shell_var.cut_sta,shell_var.cut_size);
}

/***** 设置接收响应 *****/
//   @E=1@T=2@A=1@P=?@W=2@d=4@D=4S@S=1@F=1@B=4800@C=9600@V=1@W=2@d=4       @A=0
void set_recv_resp(cmd_node* node){
    sscanf(node->val,"%d",&shell_var.recv_resp);
    if(0==shell_var.recv_resp){
        printf("----> ignore receive response\n");
    }else if(1==shell_var.recv_resp){
        printf("----> allow receive response\n");
    }
}
//@E=1@H=4567@A=1@P=?@W=2@d=4@V=1@S=1
void insert_identify(cmd_node* node){
    write_collect((uint8_t*)node->val,strlen(node->val),0);
}

/***** 继电器控制 *****/
//@E=1@DO1=1@A=1@P=?@W=2@d=4@V=1@S=1
void relay_control(cmd_node* node){
    int relay_num;
    char val;
    uint8_t status[1];
    sscanf(node->key,"DO%d",&relay_num);
    sscanf(node->val,"%c",&val);
    switch(val){
        case '0':   //关继电器
            printf("----> relay: %d, turn off\n",relay_num);
            break;
        case '1':   //开继电器

            printf("----> relay: %d, turn on\n",relay_num);
            break;
        case '?':   //上报继电器状态
            printf("----> upload relay status\n");

            status[0]=1;           //TODO 读取引脚电平后传入
            write_collect(&status[0],sizeof(status),0);
            break;
        default:
            return;
    }
}
//@E=1@DO1=0@DI1=1@DO2=1@A=1@P=?@W=2@d=4@V=1@S=1
void trigger_collect(cmd_node* node){
    int collect_num;
    char val;
    uint8_t status[1];
    if(!strcmp(node->val,"")){
        printf("----> cancel the collect\n");
        //TODO 删除所有采集规则
        return;
    }
    sscanf(node->key,"DI%d",&collect_num);
    sscanf(node->val,"%c",&val);

    switch(val){                //TODO 设置引脚 下降沿\上升沿 回调采集
        case '0':
            printf("----> %d falling edge trigger collect\n",collect_num);
            break;
        case '1':
            printf("----> %d rising edge trigger collect\n",collect_num);
            break;
        case '2':
            printf("----> %d falling or rising edge trigger collect\n",collect_num);
            break;
        case '?':
            printf("----> %d falling edge trigger collect\n",collect_num);
            //write_collect()
            break;
        default:
            return;
    }
}

/***** AI值上报 *****/
//@E=1@DO1=0@AI1=?@V=1@S=1
void upload_AI(cmd_node* node){
    int AI_num;
    char val;
    uint8_t status[4];
    sscanf(node->key,"AI%d",&AI_num);
    sscanf(node->val,"%c",&val);
    if(val=='?'){
        printf("----> upload AI: %d\n",AI_num);
        //write_collect(status,sizeof(status),0);
    }
}

//@E=1@DO1=0@C=AA55hello@S=1
void execute_cmd(cmd_node* node){
    uint16_t check=0;
    uint8_t buf[2];
    if(!strncmp(node->key,"C",strlen("C"))&&0!=strncmp(EXEC_IDENTIFY,node->val,strlen(EXEC_IDENTIFY))){
        printf("----> head not %s\n",EXEC_IDENTIFY);
        return;
    }
    //printf("----> execute cmd: %s\n",node->val);

    if(!strncmp(&node->val[strlen(node->val)-2],"V1",strlen("V1"))) {
        check = get_crc((uint8_t *) node->val, strlen(node->val) - 2);
        buf[0] = (uint8_t) (check >> 8);
        buf[1] = (uint8_t) check;
        write_collect(buf, 2, 0);
        printf("----> insert CRC check: %x\n",check);   //先写入校验，再执行命令

        if(node->key[0]=='O'){
            search_execute_handle(node->val,strlen(node->val)-2);
        }else if(node->key[0]=='C'){
            search_execute_handle(&node->val[4],strlen(node->val)-2);
        }
    }else if(!strncmp(&node->val[strlen(node->val)-2],"V2",strlen("V2"))){
        check=get_sum((uint8_t*)node->val,strlen(node->val)-2);
        buf[0]=(uint8_t)(check>>8);
        buf[1]=(uint8_t)check;
        write_collect(buf,2,0);
        printf("----> insert SUM check: %x\n",check);

        if(node->key[0]=='O'){
            search_execute_handle(node->val,strlen(node->val)-2);
        }else if(node->key[0]=='C'){
            search_execute_handle(&node->val[4],strlen(node->val)-2);
        }
    }else{                      //没校验位
        if(node->key[0]=='O'){
            search_execute_handle(node->val,strlen(node->val));
        }else if(node->key[0]=='C'){
            search_execute_handle(&node->val[4],strlen(node->val));
        }
    }
}

void set_penetrate_transmit(cmd_node* node){
    if(node->val[0]=='0'){
        printf("----> turn off penetrate \n");

    }else if(node->val[0]=='1'){
        printf("----> turn on penetrate \n");

    }
}

/***** 回调表 （注意：如果头部有相同字串/字符 字符多的放上面 否则将查找错误）*****/
cmd_handle cmd_handle_group[]={   		//字符串 => 函数
        {"E",   &set_echo},             //设置回传
        {"L",   &loop},                 //M->L部分 循环执行（配合M使用）
        {"M",   &mark},                 //M标记（配合L使用）
        {"V",   &insert_check},         //发送区 插入校验
        {"Q",   &set_loop_shell},       //设置脚本无限循环执行
        {"T",   &set_inform_period},    //设置上报周期
        {"F",   &set_inform_format},    //设置上报数据格式
        {"SH",  &show_node},            //打印节点
        {"S",   &at_once_inform},       //立即上报一次（并清空发送区）
        {"P",   &set_packet_num},       //发送区放置4字节包序号
        {"B",   &set_baud_rate},        //设置波特率
        {"H",   &insert_identify},      //发送区插入标识
        {"DO",  &relay_control},        //继电器控制 （必须在D命令上）
        {"DI",  &trigger_collect},      //触发采集
        {"D",   &delay},                //延时
        {"AI",  &upload_AI},            //预留接口
        {"A",   &set_recv_resp},        //设置是否接收应答
        {"CUT", &cut_collect},          //截取部分数据发送（必须在C命令上）
        {"C",   &execute_cmd},          //执行命令（校验命令头）
        {"O",   &execute_cmd},          //直接执行命令（不校验命令头）
        {"SSW", &set_penetrate_transmit},   //设置透传
};

int search_cmd_handle(cmd_node* node){		//遍历查询表 回调
    static int i,cmd_len;
    cmd_len=sizeof(cmd_handle_group)/sizeof(cmd_handle);
    if(1==shell_var.wait_loop){
        if(0!=strncmp(node->key,"L",strlen("L")))
            return 0;
    }
    for(i=0;i<cmd_len;i++){
        if(!strncmp(cmd_handle_group[i].cmd,node->key,strlen(cmd_handle_group[i].cmd))){
            if(NULL!=cmd_handle_group[i].func){
                cmd_handle_group[i].func(node);
                return 0;
            }else
                return -1;
        }
    }
    return -1;
}



int search_execute_handle(char* data,int len){		//遍历查询表 回调
    static int i;
    for(i=0;i<shell_var.execute_handle_len;i++){
        if(!strncmp(shell_var.execute_handle_group[i].cmd,&data[0],strlen(shell_var.execute_handle_group[i].cmd))){
            if(NULL!=shell_var.execute_handle_group[i].func){
                shell_var.execute_handle_group[i].func(data,len);
                return 0;
            }else
                return -1;
        }
    }
    return -1;
}

/***** 注册发送服务 *****/
int register_inform(send_handle f){
    if(NULL!=f){
        shell_var.send_data=f;
        return 0;
    }
    return -1;
}

/***** 注册用户执行服务 *****/
int register_execute(execute_handle* group,int handle_size){
    if(NULL!=group&&0!=handle_size){
        shell_var.execute_handle_group=group;
        shell_var.execute_handle_len=handle_size;
        return 0;
    }

    return -1;

}

/***** 恢复参数 脚本执行完后 将调用*****/
void var_restore(){
    if(1!=shell_var.recv_resp) {                    //恢复接收应答
        shell_var.recv_resp=1;
    }
    if(DEFAULT_BAUD_RATE!=shell_var.baud_rate){     //恢复波特率
        shell_var.baud_rate=DEFAULT_BAUD_RATE;
        UART_Init(shell_var.baud_rate);
    }
    if(0!=shell_var.cut_sta||0!=shell_var.cut_size){ //恢复为 不截取数据
        shell_var.cut_sta=0;
        shell_var.cut_size=0;
    }
}

/***** 执行完后 回收内存 恢复参数 *****/
void recycle() {
    clean_node_list();        //释放内存
    clean_shell_buf();
    var_restore();
    ++shell_var.packet_num;
}

/***** 执行命令 *****/
int execute(cmd_node* handle,int len){
    cmd_node* p;
    if(0>=len) {
        printf("----> execute failed\n");
        return -1;
    }
    p=handle;
    for(int i=0;i<len;i++){
        search_cmd_handle(p);     //直接传node
        p=p->next;
    }
    transmit_control();
    if(1==shell_var.shell_loop){            //无限循环执行 @Q=1
        drop_node_bynode(get_node_bykey("Q")); // falat 无限循环中 去除 @Q 节点 否则嵌套循环 导致内存溢出
        //show_node(0);
        while(1) {
            printf("--------- endless loop -----------\n");
            p = handle;
            for (int i = 0; i < shell_var.node_num; i++) {
                search_cmd_handle(p);     //直接传node
                p = p->next;
            }
            transmit_control();     //TODO M -> L 循环内 要上报吗？
            if (!strncmp(shell_var.shell_buf, "EXIT", strlen("EXIT"))) {
                printf("EXIT @Q endless loop\n");
                shell_var.shell_loop = 0;
                break;
            }
        }
    }
    //execute_end();            //这里回收会影响 @L 命令
//    clean_shell_buf();        //TODO 可能导致无法校验
    return 0;
}

/***** 打印节点 *****/
void show_node(cmd_node* node){
    cmd_node* p;
    int show_num=0;
    if(node!=NULL){
        sscanf(node->val,"%d",&show_num);
    }
    p=shell_var.head;
    if(show_num==0||show_num>=get_node_num()){
        show_num=get_node_num();
    }
    for(int i=0;i<show_num;i++){       //打印键值对
        printf("%s >> %s\n",p->key,p->val);
        p=p->next;
    }
}

